from Config.myConstant import *
from Config.myConfig import *
from DataAccess.TradedayDataProcess import TradedayDataProcess
from DataPrepare.tickFactorsProcess import tickFactorsProcess
from DataAccess.KLineDataProcess import KLineDataProcess
from DataPrepare.dailyFactorsProcess import dailyFactorsProcess
from Utility.JobLibUtility import JobLibUtility
from typing import List as type_list
from Strategy.baseStrategy.baseStrategy import baseStrategy
import pandas as pd
import numpy as np
import math
import xgboost as xgb
import warnings
from DataAccess.TickDataProcess import TickDataProcess
from DataPrepare.tickFactors.tickDataPrepared import tickDataPrepared
from DataAccess.IndexComponentDataProcess import IndexComponentDataProcess
from Utility.InfluxdbUtility import InfluxdbUtility
########################################################################
class gradeStrategyTWAP(baseStrategy):
    """按照预测值进行交易"""
    #----------------------------------------------------------------------
    def __init__(self):
        self.name='按照CNN的预测值进行TWAP交易'
        pass
    #----------------------------------------------------------------------
    def multipleCodes_parallel(self,codes:type_list[str],startDate:str,endDate:str,parameters=[]):
        mydata=JobLibUtility.useJobLibToComputeByCodes(self.multipleCodes,codes,MYGROUPS,startDate,endDate,parameters)
        return mydata
        pass
    #----------------------------------------------------------------------
    #输入code=600000.SH，startdate=yyyyMMdd，endDate=yyyyMMdd
    def multipleCodes(self,codes:type_list[str],startDate:str,endDate:str,parameters=[]):
        mydata=[]
        for i in range(len(codes)):
            code=codes[i]
            data=self.singleCode(code,startDate,endDate,parameters)
            mydata.append(data)
        mydata=pd.concat(mydata)
        return mydata
    
    #----------------------------------------------------------------------
    def singleCode(self,code:str,startDate:str,endDate:str,parameters=[]):
        startDate=str(startDate)
        endDate=str(endDate)
        days=list(TradedayDataProcess().getTradedays(startDate,endDate))
        myWeight=IndexComponentDataProcess.getStockPropertyInIndex(code,HS300,startDate,endDate)
        tick=TickDataProcess()
        tickFactor=tickDataPrepared()
        featureColumns=['predictMaxNext2m','predictMinNext2m']
        trade=[]
        for day in days:
            tickData=tick.getTickShotDataFromInfluxdbServer(code,day)
            if tickData.shape[0]==0:
                continue
            preClose=tickData['dailyPreClose'].iloc[0]
            data=InfluxdbUtility.getDataFromInfluxdb(code,day,'MaoTickPredict20190708',columns=featureColumns)
            if data.shape[0]==0:
                continue
            tickData=pd.merge(tickData,data,how='left',left_index=True,right_index=True)
            weight=myWeight[myWeight.index==str(day)]['weight'].iloc[0]
            if np.isnan(weight)==True:
                continue
            maxPosition=round(100000000*(weight/100)/preClose,-2)
            if maxPosition<100:
                continue
            parameters={'maxPosition':maxPosition,'longOpen':0.015,'shortOpen':-0.015,'longClose':0.01,'shortClose':-0.01,'transactionRatio':0.1}
            for col in featureColumns:
                if (col in list(tickData.columns))==False:
                    continue
                if tickData[col].isna().sum()==tickData.shape[0]:
                    continue
            trade0=self.strategy(tickData,parameters)
            trade.append(trade0)
            pass
        if len(trade)==0:
            trade=pd.DataFrame()
        else:
            trade=pd.concat(trade)
            if trade.shape[0]==0:
                return pd.DataFrame()
            trade['code']=code
            logger.info(f'backtest of {code} complete!!')
        return trade
        pass
     #----------------------------------------------------------------------
    def strategy(self,data:pd.DataFrame,parameters):
        
        myindex={}
        select=list(data.columns)
        for item in data.columns:
            myindex.update({item:select.index(item)})
        mydata=data.values
        openPrice=0
        maxPrice=0
        minPrice=0
        stop=False
        maxDownDraw=0
        trade=[]
        dict={}
        twapBasis=0
        twapBuy=0
        twapSell=0
        tradeBaisNum=4
        maxnum=0
        #从9点31分开始交易到14点55
        #利用lastprice统计twap价格
        for num in range(940):
            i=num*5+20
            if i<len(mydata):
                tick=mydata[i] 
                lastPrice=tick[myindex['lastPrice']]
                twapBasis=twapBasis+lastPrice
                maxnum=num+1
                pass
            else:
                break
                pass
        twapBasis=twapBasis/maxnum


        #统计twapbuy的价格
        alreadyTradeNum=0
        num=0
        while num<maxnum:
            i=num*5+20
            tick=mydata[i] 
            maxPredict=tick[myindex['predictMaxNext2m']]/100.0
            minPredict=tick[myindex['predictMinNext2m']]/100.0
            midPredict=(maxPredict+minPredict)/2
            realData=tick[myindex['realData']]
            S1=tick[myindex['S1']]
            B1=tick[myindex['B1']]
            SV1=tick[myindex['SV1']]
            BV1=tick[myindex['BV1']]
            time=tick[myindex['tick']]
            date=tick[myindex['date']]
            increaseToday=tick[myindex['midPrice']]/tick[myindex['dailyPreClose']]-1
            lastPrice=tick[myindex['lastPrice']]
            if (maxPredict>0.015) & (midPredict>0.005) & (num<maxnum-2):
                canTradeNum=min(tradeBaisNum,maxnum-alreadyTradeNum)
                twapBuy=twapBuy+S1*canTradeNum
                alreadyTradeNum+canTradeNum
                num=num+canTradeNum-1
                pass
            elif (minPredict<-0.015) & (midPredict<-0.005) & (num<maxnum-2):
                num=min(maxnum-1,num+tradeBaisNum-1)
            elif (alreadyTradeNum<(num+1)):
                canTradeNum=num+1-alreadyTradeNum
                twapBuy=twapBuy+S1*canTradeNum
                alreadyTradeNum=alreadyTradeNum+canTradeNum
                num=num+1
        twapBuy=twapBuy/alreadyTradeNum
        
        #统计twapsell的价格
        alreadyTradeNum=0
        num=0
        while num<maxnum:
            i=num*5+20
            tick=mydata[i] 
            maxPredict=tick[myindex['predictMaxNext2m']]/100.0
            minPredict=tick[myindex['predictMinNext2m']]/100.0
            midPredict=(maxPredict+minPredict)/2
            realData=tick[myindex['realData']]
            S1=tick[myindex['S1']]
            B1=tick[myindex['B1']]
            SV1=tick[myindex['SV1']]
            BV1=tick[myindex['BV1']]
            time=tick[myindex['tick']]
            date=tick[myindex['date']]
            increaseToday=tick[myindex['midPrice']]/tick[myindex['dailyPreClose']]-1
            lastPrice=tick[myindex['lastPrice']]
            if (maxPredict>0.015) & (midPredict>0.005) & (num<maxnum-2):
                num=min(maxnum-1,num+tradeBaisNum-1)
                pass
            elif (minPredict<-0.015) & (midPredict<-0.005) & (num<maxnum-2):
                canTradeNum=min(tradeBaisNum,maxnum-alreadyTradeNum)
                twapSell=twapSell+B1*canTradeNum
                alreadyTradeNum+canTradeNum
                num=num+canTradeNum-1
            elif (alreadyTradeNum<(num+1)):
                canTradeNum=num+1-alreadyTradeNum
                twapSell=twapSell+B1*canTradeNum
                alreadyTradeNum=alreadyTradeNum+canTradeNum
                num=num+1
        twapSell=twapSell/alreadyTradeNum

        dict={'date':date,'twapBasis':twapBasis,'twapBuy':twapBuy,'twapSell':twapSell}
        trade.append(dict)
        trade=pd.DataFrame(data=trade)    
        #print(trade)
        return trade
########################################################################
